﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Transcend.DP3.Helper;

namespace Transcend.DP3.Db
{

	/// <summary>
	/// 帮助类，主要用于动态获取对象属性值
	/// </summary>
	public class ONHelper
	{

		public static object PropertyValue(object obj, string[] part, int startPos)
		{

			ExHelper.NotNull(obj, string.Format("取对象属性值失败，对象属性{0}空引用", string.Join(".", part, 0, startPos)));

			PropertyInfo p = null;
			Type t = obj.GetType();
			string pName = null;
			int keyStartPos = startPos;

			if (startPos == part.Length) return obj;

			while (startPos < part.Length)
			{
				pName = part[startPos];
				p = t.GetProperty(pName);
				if (p == null)
				{
					p = t.GetProperty("Item", typeof(object), new Type[] { typeof(string) });
					if (p != null && IsIndexer(p))
					{
						return PropertyValue(IndexerValue(obj, p, part, ref startPos), part, startPos);
					}
					else
					{
						ExHelper.InvalidArgument(string.Format("解析表达式{0}出错，对象{1}不包含{2}属性", string.Join(".", part), t.Name, pName));
					}
				}
				else
				{
					if (IsIndexer(p))
					{
						return PropertyValue(IndexerValue(obj, p, part, ref startPos), part, startPos);
					}
					else
					{
						return PropertyValue(p.GetValue(obj, null), part, ++startPos);
					}
				}
			}

			return obj;

		}

		/// <summary>
		/// 判断属性是否为索引器
		/// </summary>
		/// <param name="p"></param>
		/// <returns></returns>
		private static bool IsIndexer(PropertyInfo p)
		{
			return p.GetIndexParameters().Length > 0;
		}

		/// <summary>
		/// 取索引器值
		/// </summary>
		/// <param name="obj"></param>
		/// <param name="p"></param>
		/// <param name="part"></param>
		/// <param name="startPos"></param>
		/// <returns></returns>
		private static object IndexerValue(object obj, PropertyInfo p, string[] part, ref int startPos)
		{
			object pValue = null;
			int keyPos = startPos;
			string key = null;
			while (pValue == null && startPos < part.Length)
			{
				key = string.Join(".", part, keyPos, startPos - keyPos + 1);
				pValue = p.GetValue(obj, new object[] { key });
				++startPos;
			}
			return pValue;
		}

	}

}
